<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/xiehuan.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/xiehuan.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT" />










<meta name="description" content="SpringMVC">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringMVC">
<meta property="og:url" content="http://yoursite.com/2019/11/18/SpringMVC/index.html">
<meta property="og:site_name" content="xiehuan">
<meta property="og:description" content="SpringMVC">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-12-09T06:31:49.330Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="SpringMVC">
<meta name="twitter:description" content="SpringMVC">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2019/11/18/SpringMVC/"/>





  <title>SpringMVC | xiehuan</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">xiehuan</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/11/18/SpringMVC/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="xiehuan">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="xiehuan">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">SpringMVC</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-11-18T19:55:43+08:00">
                2019-11-18
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>SpringMVC<br><a id="more"></a><br>说到SpringMVC的启动过程，就要讲讲tomcat加载的过程了(这里只主要讲tomcat是怎么加载spring项目的)</p>
<p>Bootstrap类<br>LifecycleBase的start()方法<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">startInternal();//第150行</span><br></pre></td></tr></table></figure></p>
<p>StandardContext继承了LifecycleBase类，并  重写startInternal这个方法<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">// Configure and call application event listeners 5254行</span><br><span class="line">if (ok) &#123;</span><br><span class="line">    if (!listenerStart()) &#123;</span><br><span class="line">        log.error(sm.getString(&quot;standardContext.listenerFail&quot;));</span><br><span class="line">        ok = false;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这里调用了listenerStart()方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Configure the set of instantiated application event listeners</span><br><span class="line"> * for this Context.</span><br><span class="line"> * @return &lt;code&gt;true&lt;/code&gt; if all listeners wre</span><br><span class="line"> * initialized successfully, or &lt;code&gt;false&lt;/code&gt; otherwise.</span><br><span class="line"> */</span><br><span class="line">public boolean listenerStart() &#123;</span><br><span class="line"></span><br><span class="line">    if (log.isDebugEnabled())</span><br><span class="line">        log.debug(&quot;Configuring application event listeners&quot;);</span><br><span class="line"></span><br><span class="line">    // Instantiate the required listeners</span><br><span class="line">    String listeners[] = findApplicationListeners();</span><br><span class="line">    Object results[] = new Object[listeners.length];</span><br><span class="line">    boolean ok = true;</span><br><span class="line">    for (int i = 0; i &lt; results.length; i++) &#123;</span><br><span class="line">        if (getLogger().isDebugEnabled())</span><br><span class="line">            getLogger().debug(&quot; Configuring event listener class &apos;&quot; +</span><br><span class="line">                listeners[i] + &quot;&apos;&quot;);</span><br><span class="line">        try &#123;</span><br><span class="line">            String listener = listeners[i];</span><br><span class="line">            results[i] = getInstanceManager().newInstance(listener);</span><br><span class="line">        &#125; catch (Throwable t) &#123;</span><br><span class="line">            t = ExceptionUtils.unwrapInvocationTargetException(t);</span><br><span class="line">            ExceptionUtils.handleThrowable(t);</span><br><span class="line">            getLogger().error(sm.getString(</span><br><span class="line">                    &quot;standardContext.applicationListener&quot;, listeners[i]), t);</span><br><span class="line">            ok = false;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if (!ok) &#123;</span><br><span class="line">        getLogger().error(sm.getString(&quot;standardContext.applicationSkipped&quot;));</span><br><span class="line">        return false;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // Sort listeners in two arrays</span><br><span class="line">    ArrayList&lt;Object&gt; eventListeners = new ArrayList&lt;&gt;();</span><br><span class="line">    ArrayList&lt;Object&gt; lifecycleListeners = new ArrayList&lt;&gt;();</span><br><span class="line">    for (int i = 0; i &lt; results.length; i++) &#123;</span><br><span class="line">        if ((results[i] instanceof ServletContextAttributeListener)</span><br><span class="line">            || (results[i] instanceof ServletRequestAttributeListener)</span><br><span class="line">            || (results[i] instanceof ServletRequestListener)</span><br><span class="line">            || (results[i] instanceof HttpSessionIdListener)</span><br><span class="line">            || (results[i] instanceof HttpSessionAttributeListener)) &#123;</span><br><span class="line">            eventListeners.add(results[i]);</span><br><span class="line">        &#125;</span><br><span class="line">        if ((results[i] instanceof ServletContextListener)</span><br><span class="line">            || (results[i] instanceof HttpSessionListener)) &#123;</span><br><span class="line">            lifecycleListeners.add(results[i]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // Listener instances may have been added directly to this Context by</span><br><span class="line">    // ServletContextInitializers and other code via the pluggability APIs.</span><br><span class="line">    // Put them these listeners after the ones defined in web.xml and/or</span><br><span class="line">    // annotations then overwrite the list of instances with the new, full</span><br><span class="line">    // list.</span><br><span class="line">    for (Object eventListener: getApplicationEventListeners()) &#123;</span><br><span class="line">        eventListeners.add(eventListener);</span><br><span class="line">    &#125;</span><br><span class="line">    setApplicationEventListeners(eventListeners.toArray());</span><br><span class="line">    for (Object lifecycleListener: getApplicationLifecycleListeners()) &#123;</span><br><span class="line">        lifecycleListeners.add(lifecycleListener);</span><br><span class="line">        if (lifecycleListener instanceof ServletContextListener) &#123;</span><br><span class="line">            noPluggabilityListeners.add(lifecycleListener);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    setApplicationLifecycleListeners(lifecycleListeners.toArray());</span><br><span class="line"></span><br><span class="line">    // Send application start events</span><br><span class="line"></span><br><span class="line">    if (getLogger().isDebugEnabled())</span><br><span class="line">        getLogger().debug(&quot;Sending application start events&quot;);</span><br><span class="line"></span><br><span class="line">    // Ensure context is not null</span><br><span class="line">    getServletContext();</span><br><span class="line">    context.setNewServletContextListenerAllowed(false);</span><br><span class="line"></span><br><span class="line">    Object instances[] = getApplicationLifecycleListeners();</span><br><span class="line">    if (instances == null || instances.length == 0) &#123;</span><br><span class="line">        return ok;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ServletContextEvent event = new ServletContextEvent(getServletContext());</span><br><span class="line">    ServletContextEvent tldEvent = null;</span><br><span class="line">    if (noPluggabilityListeners.size() &gt; 0) &#123;</span><br><span class="line">        noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext());</span><br><span class="line">        tldEvent = new ServletContextEvent(noPluggabilityServletContext);</span><br><span class="line">    &#125;</span><br><span class="line">    for (int i = 0; i &lt; instances.length; i++) &#123;</span><br><span class="line">        if (!(instances[i] instanceof ServletContextListener))</span><br><span class="line">            continue;</span><br><span class="line">        ServletContextListener listener =</span><br><span class="line">            (ServletContextListener) instances[i];</span><br><span class="line">        try &#123;</span><br><span class="line">            fireContainerEvent(&quot;beforeContextInitialized&quot;, listener);</span><br><span class="line">            if (noPluggabilityListeners.contains(listener)) &#123;</span><br><span class="line">                listener.contextInitialized(tldEvent);</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                listener.contextInitialized(event);</span><br><span class="line">            &#125;</span><br><span class="line">            fireContainerEvent(&quot;afterContextInitialized&quot;, listener);</span><br><span class="line">        &#125; catch (Throwable t) &#123;</span><br><span class="line">            ExceptionUtils.handleThrowable(t);</span><br><span class="line">            fireContainerEvent(&quot;afterContextInitialized&quot;, listener);</span><br><span class="line">            getLogger().error</span><br><span class="line">                (sm.getString(&quot;standardContext.listenerStart&quot;,</span><br><span class="line">                              instances[i].getClass().getName()), t);</span><br><span class="line">            ok = false;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return (ok);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在这个方法里面，调用了ContextLoaderListener类的contextInitialized方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Initialize the root web application context.</span><br><span class="line"> */</span><br><span class="line">@Override</span><br><span class="line">public void contextInitialized(ServletContextEvent event) &#123;</span><br><span class="line">	initWebApplicationContext(event.getServletContext());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>contextInitialized 方法调用了父类的initWebApplicationContext方法，开始初始化context</p>
<p><strong>简述：tomcat调用了ContextLoaderListener类的contextInitialized方法</strong></p>
<p>这个时候就要问了，这样来看的说web.xml文件是在什么时候加载的呢</p>
<h3 id="StandardContext类"><a href="#StandardContext类" class="headerlink" title="StandardContext类"></a>StandardContext类</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br></pre></td><td class="code"><pre><span class="line">  /**</span><br><span class="line">   * 启动组件</span><br><span class="line">   * 实现此接口&#123;@link org.apache.catalina.util.LifecycleBase#startInternal()&#125;.</span><br><span class="line">   *</span><br><span class="line">   * @exception 如果此组件检测到阻止使用此组件的致命错误 ，就抛出LifecycleException异常</span><br><span class="line">   *  </span><br><span class="line">   */</span><br><span class="line">  @Override</span><br><span class="line">  protected synchronized void startInternal() throws LifecycleException &#123;</span><br><span class="line"></span><br><span class="line">      if(log.isDebugEnabled())</span><br><span class="line">          log.debug(&quot;Starting &quot; + getBaseName());</span><br><span class="line"></span><br><span class="line">      // 发送 j2ee.state.starting通知</span><br><span class="line">      if (this.getObjectName() != null) &#123;</span><br><span class="line">          Notification notification = new Notification(&quot;j2ee.state.starting&quot;,</span><br><span class="line">                  this.getObjectName(), sequenceNumber.getAndIncrement());</span><br><span class="line">          broadcaster.sendNotification(notification);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      setConfigured(false);</span><br><span class="line">      boolean ok = true;</span><br><span class="line"></span><br><span class="line">      // 目前这实际上是一个NO-OP，但需要调用它来确保namingsources遵循正确的生命周期</span><br><span class="line">      if (namingResources != null) &#123;</span><br><span class="line">          namingResources.start();</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      // 工作目录</span><br><span class="line">      postWorkDirectory();</span><br><span class="line"></span><br><span class="line">      // 根据需要添加缺少的组件</span><br><span class="line">      if (getResources() == null) &#123;   // (1) Required by Loader</span><br><span class="line">          if (log.isDebugEnabled())</span><br><span class="line">              log.debug(&quot;Configuring default Resources&quot;);</span><br><span class="line"></span><br><span class="line">          try &#123;</span><br><span class="line">              setResources(new StandardRoot(this));</span><br><span class="line">          &#125; catch (IllegalArgumentException e) &#123;</span><br><span class="line">              log.error(sm.getString(&quot;standardContext.resourcesInit&quot;), e);</span><br><span class="line">              ok = false;</span><br><span class="line">          &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      if (ok) &#123;</span><br><span class="line">          resourcesStart();</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      if (getLoader() == null) &#123;</span><br><span class="line">          WebappLoader webappLoader = new WebappLoader(getParentClassLoader());</span><br><span class="line">          webappLoader.setDelegate(getDelegate());</span><br><span class="line">          setLoader(webappLoader);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      // 尚未指定显式cookie处理器；请使用默认值</span><br><span class="line">      if (cookieProcessor == null) &#123;</span><br><span class="line">          cookieProcessor = new Rfc6265CookieProcessor();</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      // 初始化字符集映射器</span><br><span class="line">      getCharsetMapper();</span><br><span class="line"></span><br><span class="line">      // 验证所需扩展</span><br><span class="line">      boolean dependencyCheck = true;</span><br><span class="line">      try &#123;</span><br><span class="line">          dependencyCheck = ExtensionValidator.validateApplication</span><br><span class="line">              (getResources(), this);</span><br><span class="line">      &#125; catch (IOException ioe) &#123;</span><br><span class="line">          log.error(sm.getString(&quot;standardContext.extensionValidationError&quot;), ioe);</span><br><span class="line">          dependencyCheck = false;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      if (!dependencyCheck) &#123;</span><br><span class="line">          // 如果依赖项检查失败，则不使应用程序可用</span><br><span class="line">          ok = false;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      // 读取“catalina.useNaming”环境变量</span><br><span class="line">      String useNamingProperty = System.getProperty(&quot;catalina.useNaming&quot;);</span><br><span class="line">      if ((useNamingProperty != null)</span><br><span class="line">          &amp;&amp; (useNamingProperty.equals(&quot;false&quot;))) &#123;</span><br><span class="line">          useNaming = false;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      if (ok &amp;&amp; isUseNaming()) &#123;</span><br><span class="line">          if (getNamingContextListener() == null) &#123;</span><br><span class="line">              NamingContextListener ncl = new NamingContextListener();</span><br><span class="line">              ncl.setName(getNamingContextName());</span><br><span class="line">              ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite());</span><br><span class="line">              addLifecycleListener(ncl);</span><br><span class="line">              setNamingContextListener(ncl);</span><br><span class="line">          &#125;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      // 标准容器启动</span><br><span class="line">      if (log.isDebugEnabled())</span><br><span class="line">          log.debug(&quot;Processing standard container startup&quot;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">      // Binding thread</span><br><span class="line">      ClassLoader oldCCL = bindThread();</span><br><span class="line"></span><br><span class="line">      try &#123;</span><br><span class="line">          if (ok) &#123;</span><br><span class="line">              // 启动我们的下属组件（如果有）</span><br><span class="line">              Loader loader = getLoader();</span><br><span class="line">              if (loader instanceof Lifecycle) &#123;</span><br><span class="line">                  ((Lifecycle) loader).start();</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">              // 由于加载程序刚刚启动，webapp类加载程序现在创建</span><br><span class="line">              setClassLoaderProperty(&quot;clearReferencesRmiTargets&quot;,</span><br><span class="line">                      getClearReferencesRmiTargets());</span><br><span class="line">              setClassLoaderProperty(&quot;clearReferencesStopThreads&quot;,</span><br><span class="line">                      getClearReferencesStopThreads());</span><br><span class="line">              setClassLoaderProperty(&quot;clearReferencesStopTimerThreads&quot;,</span><br><span class="line">                      getClearReferencesStopTimerThreads());</span><br><span class="line">              setClassLoaderProperty(&quot;clearReferencesHttpClientKeepAliveThread&quot;,</span><br><span class="line">                      getClearReferencesHttpClientKeepAliveThread());</span><br><span class="line">              setClassLoaderProperty(&quot;clearReferencesObjectStreamClassCaches&quot;,</span><br><span class="line">                      getClearReferencesObjectStreamClassCaches());</span><br><span class="line"></span><br><span class="line">              // 通过连续调用unbindThread和bindThread，我们将当前线程CCL设置为webapp类加载器</span><br><span class="line">              unbindThread(soldCCL);</span><br><span class="line">              oldCCL = bindThread();</span><br><span class="line"></span><br><span class="line">              // 重新初始化logger。其他组件可能使用它太早了，所以应该重置它。</span><br><span class="line">              logger = null;</span><br><span class="line">              getLogger();</span><br><span class="line"></span><br><span class="line">              Realm realm = getRealmInternal();</span><br><span class="line">              if(null != realm) &#123;</span><br><span class="line">                  if (realm instanceof Lifecycle) &#123;</span><br><span class="line">                      ((Lifecycle) realm).start();</span><br><span class="line">                  &#125;</span><br><span class="line"></span><br><span class="line">			//将CredentialHandler放入ServletContext中，以便应用程序可以访问它。将它包装在一个“安全”处理程序中，</span><br><span class="line">			//这样应用程序就不能修改它。</span><br><span class="line">                  CredentialHandler safeHandler = new CredentialHandler() &#123;</span><br><span class="line">                      @Override</span><br><span class="line">                      public boolean matches(String inputCredentials, String storedCredentials) &#123;</span><br><span class="line">                          return getRealmInternal().getCredentialHandler().matches(inputCredentials, storedCredentials);</span><br><span class="line">                      &#125;</span><br><span class="line"></span><br><span class="line">                      @Override</span><br><span class="line">                      public String mutate(String inputCredentials) &#123;</span><br><span class="line">                          return getRealmInternal().getCredentialHandler().mutate(inputCredentials);</span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;;</span><br><span class="line">                  context.setAttribute(Globals.CREDENTIAL_HANDLER, safeHandler);</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">              // Notify our interested LifecycleListeners</span><br><span class="line">              fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);</span><br><span class="line"></span><br><span class="line">              // 启动子容器（如果尚未启动）</span><br><span class="line">              for (Container child : findChildren()) &#123;</span><br><span class="line">                  if (!child.getState().isAvailable()) &#123;</span><br><span class="line">                      child.start();</span><br><span class="line">                  &#125;</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">              // Start the Valves in our pipeline (including the basic),</span><br><span class="line">              // if any</span><br><span class="line">              if (pipeline instanceof Lifecycle) &#123;</span><br><span class="line">                  ((Lifecycle) pipeline).start();</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">              // 获取管理器</span><br><span class="line">              Manager contextManager = null;</span><br><span class="line">              Manager manager = getManager();</span><br><span class="line">              if (manager == null) &#123;</span><br><span class="line">                  if (log.isDebugEnabled()) &#123;</span><br><span class="line">                      log.debug(sm.getString(&quot;standardContext.cluster.noManager&quot;,</span><br><span class="line">                              Boolean.valueOf((getCluster() != null)),</span><br><span class="line">                              Boolean.valueOf(distributable)));</span><br><span class="line">                  &#125;</span><br><span class="line">                  if ( (getCluster() != null) &amp;&amp; distributable) &#123;</span><br><span class="line">                      try &#123;</span><br><span class="line">                          contextManager = getCluster().createManager(getName());</span><br><span class="line">                      &#125; catch (Exception ex) &#123;</span><br><span class="line">                          log.error(&quot;standardContext.clusterFail&quot;, ex);</span><br><span class="line">                          ok = false;</span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125; else &#123;</span><br><span class="line">                      contextManager = new StandardManager();</span><br><span class="line">                  &#125;</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">              // 如果未指定，则配置默认管理器</span><br><span class="line">              if (contextManager != null) &#123;</span><br><span class="line">                  if (log.isDebugEnabled()) &#123;</span><br><span class="line">                      log.debug(sm.getString(&quot;standardContext.manager&quot;,</span><br><span class="line">                              contextManager.getClass().getName()));</span><br><span class="line">                  &#125;</span><br><span class="line">                  setManager(contextManager);</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line">              if (manager!=null &amp;&amp; (getCluster() != null) &amp;&amp; distributable) &#123;</span><br><span class="line">                  //让集群知道有一个可分发的上下文，并且它有自己的管理器</span><br><span class="line">                  getCluster().registerManager(manager);</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          if (!getConfigured()) &#123;</span><br><span class="line">              log.error(sm.getString(&quot;standardContext.configurationFail&quot;));</span><br><span class="line">              ok = false;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 我们将资源放入servlet上下文中</span><br><span class="line">          if (ok)</span><br><span class="line">              getServletContext().setAttribute</span><br><span class="line">                  (Globals.RESOURCES_ATTR, getResources());</span><br><span class="line"></span><br><span class="line">          if (ok ) &#123;</span><br><span class="line">              if (getInstanceManager() == null) &#123;</span><br><span class="line">                  javax.naming.Context context = null;</span><br><span class="line">                  if (isUseNaming() &amp;&amp; getNamingContextListener() != null) &#123;</span><br><span class="line">                      context = getNamingContextListener().getEnvContext();</span><br><span class="line">                  &#125;</span><br><span class="line">                  Map&lt;String, Map&lt;String, String&gt;&gt; injectionMap = buildInjectionMap(</span><br><span class="line">                          getIgnoreAnnotations() ? new NamingResourcesImpl(): getNamingResources());</span><br><span class="line">                  setInstanceManager(new DefaultInstanceManager(context,</span><br><span class="line">                          injectionMap, this, this.getClass().getClassLoader()));</span><br><span class="line">              &#125;</span><br><span class="line">              getServletContext().setAttribute(</span><br><span class="line">                      InstanceManager.class.getName(), getInstanceManager());</span><br><span class="line">              InstanceManagerBindings.bind(getLoader().getClassLoader(), getInstanceManager());</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 创建所需的上下文属性</span><br><span class="line">          if (ok) &#123;</span><br><span class="line">              getServletContext().setAttribute(</span><br><span class="line">                      JarScanner.class.getName(), getJarScanner());</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 设置context init params</span><br><span class="line">          mergeParameters();</span><br><span class="line"></span><br><span class="line">          // 调用ServletContainerInitializers</span><br><span class="line">          for (Map.Entry&lt;ServletContainerInitializer, Set&lt;Class&lt;?&gt;&gt;&gt; entry :</span><br><span class="line">              initializers.entrySet()) &#123;</span><br><span class="line">              try &#123;</span><br><span class="line">                  entry.getKey().onStartup(entry.getValue(),</span><br><span class="line">                          getServletContext());</span><br><span class="line">              &#125; catch (ServletException e) &#123;</span><br><span class="line">                  log.error(sm.getString(&quot;standardContext.sciFail&quot;), e);</span><br><span class="line">                  ok = false;</span><br><span class="line">                  break;</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 配置并调用应用程序事件侦听器</span><br><span class="line">          if (ok) &#123;</span><br><span class="line">              if (!listenerStart()) &#123;</span><br><span class="line">                  log.error(sm.getString(&quot;standardContext.listenerFail&quot;));</span><br><span class="line">                  ok = false;</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 检查未覆盖的HTTP方法的约束需要在sci和侦听器之后，因为它们可能以编程方式更改约束</span><br><span class="line">          if (ok) &#123;</span><br><span class="line">              checkConstraintsForUncoveredMethods(findConstraints());</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          try &#123;</span><br><span class="line">              // 启动管理器</span><br><span class="line">              Manager manager = getManager();</span><br><span class="line">              if (manager instanceof Lifecycle) &#123;</span><br><span class="line">                  ((Lifecycle) manager).start();</span><br><span class="line">              &#125;</span><br><span class="line">          &#125; catch(Exception e) &#123;</span><br><span class="line">              log.error(sm.getString(&quot;standardContext.managerFail&quot;), e);</span><br><span class="line">              ok = false;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 配置和调用应用程序筛选器</span><br><span class="line">          if (ok) &#123;</span><br><span class="line">              if (!filterStart()) &#123;</span><br><span class="line">                  log.error(sm.getString(&quot;standardContext.filterFail&quot;));</span><br><span class="line">                  ok = false;</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 加载并初始化所有“启动时加载”servlet</span><br><span class="line">          if (ok) &#123;</span><br><span class="line">              if (!loadOnStartup(findChildren()))&#123;</span><br><span class="line">                  log.error(sm.getString(&quot;standardContext.servletFail&quot;));</span><br><span class="line">                  ok = false;</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          // 启动ContainerBackgroundProcessor线程</span><br><span class="line">          super.threadStart();</span><br><span class="line">      &#125; finally &#123;</span><br><span class="line">          // Unbinding thread</span><br><span class="line">          unbindThread(oldCCL);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      // 根据启动成功设置可用状态</span><br><span class="line">      if (ok) &#123;</span><br><span class="line">          if (log.isDebugEnabled())</span><br><span class="line">              log.debug(&quot;Starting completed&quot;);</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">          log.error(sm.getString(&quot;standardContext.startFailed&quot;, getName()));</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      startTime=System.currentTimeMillis();</span><br><span class="line"></span><br><span class="line">      // 发送j2ee.state.running通知</span><br><span class="line">      if (ok &amp;&amp; (this.getObjectName() != null)) &#123;</span><br><span class="line">          Notification notification =</span><br><span class="line">              new Notification(&quot;j2ee.state.running&quot;, this.getObjectName(),</span><br><span class="line">                               sequenceNumber.getAndIncrement());</span><br><span class="line">          broadcaster.sendNotification(notification);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      //WebResources实现缓存对JAR文件的引用。在某些平台上，这些引用可能会锁定JAR文件。</span><br><span class="line">//由于web应用程序启动可能已经从许多jar中读取了数据，现在触发清理。</span><br><span class="line">      getResources().gc();</span><br><span class="line"></span><br><span class="line">      // 如果出现问题，重新初始化</span><br><span class="line">      if (!ok) &#123;</span><br><span class="line">          setState(LifecycleState.FAILED);</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">          setState(LifecycleState.STARTING);</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
<h3 id="ContextConfig类"><a href="#ContextConfig类" class="headerlink" title="ContextConfig类"></a>ContextConfig类</h3><p>StandardContext默认会被添加ContextConfig（Llistener），此时会通知到它<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br></pre></td><td class="code"><pre><span class="line">   public void lifecycleEvent(LifecycleEvent event) &#123;</span><br><span class="line"></span><br><span class="line">       // Identify the context we are associated with</span><br><span class="line">       try &#123;</span><br><span class="line">           context = (Context) event.getLifecycle();</span><br><span class="line">       &#125; catch (ClassCastException e) &#123;</span><br><span class="line">           log.error(sm.getString(&quot;contextConfig.cce&quot;, event.getLifecycle()), e);</span><br><span class="line">           return;</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       // Process the event that has occurred</span><br><span class="line">       if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) &#123;</span><br><span class="line">           configureStart();</span><br><span class="line">       &#125; else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) &#123;</span><br><span class="line">           beforeStart();</span><br><span class="line">       &#125; else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) &#123;</span><br><span class="line">           // Restore docBase for management tools</span><br><span class="line">           if (originalDocBase != null) &#123;</span><br><span class="line">               context.setDocBase(originalDocBase);</span><br><span class="line">           &#125;</span><br><span class="line">       &#125; else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) &#123;</span><br><span class="line">           configureStop();</span><br><span class="line">       &#125; else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) &#123;</span><br><span class="line">           init();</span><br><span class="line">       &#125; else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) &#123;</span><br><span class="line">           destroy();</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">   protected synchronized void configureStart() &#123;</span><br><span class="line">       ...</span><br><span class="line">       webConfig();</span><br><span class="line">	...</span><br><span class="line">   &#125;</span><br><span class="line">//真实加载web.xml的方法</span><br><span class="line">//会使用digester读取web.xml并设置到StandardContext里</span><br><span class="line">   protected void webConfig() &#123;</span><br><span class="line">       /*</span><br><span class="line">        * Anything and everything can override the global and host defaults.</span><br><span class="line">        * This is implemented in two parts</span><br><span class="line">        * - Handle as a web fragment that gets added after everything else so</span><br><span class="line">        *   everything else takes priority</span><br><span class="line">        * - Mark Servlets as overridable so SCI configuration can replace</span><br><span class="line">        *   configuration from the defaults</span><br><span class="line">        */</span><br><span class="line"></span><br><span class="line">       /*</span><br><span class="line">        * The rules for annotation scanning are not as clear-cut as one might</span><br><span class="line">        * think. Tomcat implements the following process:</span><br><span class="line">        * - As per SRV.1.6.2, Tomcat will scan for annotations regardless of</span><br><span class="line">        *   which Servlet spec version is declared in web.xml. The EG has</span><br><span class="line">        *   confirmed this is the expected behaviour.</span><br><span class="line">        * - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main</span><br><span class="line">        *   web.xml is marked as metadata-complete, JARs are still processed</span><br><span class="line">        *   for SCIs.</span><br><span class="line">        * - If metadata-complete=true and an absolute ordering is specified,</span><br><span class="line">        *   JARs excluded from the ordering are also excluded from the SCI</span><br><span class="line">        *   processing.</span><br><span class="line">        * - If an SCI has a @HandlesType annotation then all classes (except</span><br><span class="line">        *   those in JARs excluded from an absolute ordering) need to be</span><br><span class="line">        *   scanned to check if they match.</span><br><span class="line">        */</span><br><span class="line">       WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(),</span><br><span class="line">               context.getXmlValidation(), context.getXmlBlockExternal());</span><br><span class="line"></span><br><span class="line">       Set&lt;WebXml&gt; defaults = new HashSet&lt;&gt;();</span><br><span class="line">       defaults.add(getDefaultWebXmlFragment(webXmlParser));</span><br><span class="line"></span><br><span class="line">       WebXml webXml = createWebXml();</span><br><span class="line"></span><br><span class="line">       // Parse context level web.xml</span><br><span class="line">       InputSource contextWebXml = getContextWebXmlSource();</span><br><span class="line">       if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) &#123;</span><br><span class="line">           ok = false;</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       ServletContext sContext = context.getServletContext();</span><br><span class="line"></span><br><span class="line">       // Ordering is important here</span><br><span class="line"></span><br><span class="line">       // Step 1. Identify all the JARs packaged with the application and those</span><br><span class="line">       // provided by the container. If any of the application JARs have a</span><br><span class="line">       // web-fragment.xml it will be parsed at this point. web-fragment.xml</span><br><span class="line">       // files are ignored for container provided JARs.</span><br><span class="line">       Map&lt;String,WebXml&gt; fragments = processJarsForWebFragments(webXml, webXmlParser);</span><br><span class="line"></span><br><span class="line">       // Step 2. Order the fragments.</span><br><span class="line">       Set&lt;WebXml&gt; orderedFragments = null;</span><br><span class="line">       orderedFragments =</span><br><span class="line">               WebXml.orderWebFragments(webXml, fragments, sContext);</span><br><span class="line"></span><br><span class="line">       // Step 3. Look for ServletContainerInitializer implementations</span><br><span class="line">       if (ok) &#123;</span><br><span class="line">           processServletContainerInitializers();</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       if  (!webXml.isMetadataComplete() || typeInitializerMap.size() &gt; 0) &#123;</span><br><span class="line">           // Step 4. Process /WEB-INF/classes for annotations and</span><br><span class="line">           // @HandlesTypes matches</span><br><span class="line">           Map&lt;String,JavaClassCacheEntry&gt; javaClassCache = new HashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">           if (ok) &#123;</span><br><span class="line">               WebResource[] webResources =</span><br><span class="line">                       context.getResources().listResources(&quot;/WEB-INF/classes&quot;);</span><br><span class="line"></span><br><span class="line">               for (WebResource webResource : webResources) &#123;</span><br><span class="line">                   // Skip the META-INF directory from any JARs that have been</span><br><span class="line">                   // expanded in to WEB-INF/classes (sometimes IDEs do this).</span><br><span class="line">                   if (&quot;META-INF&quot;.equals(webResource.getName())) &#123;</span><br><span class="line">                       continue;</span><br><span class="line">                   &#125;</span><br><span class="line">                   processAnnotationsWebResource(webResource, webXml,</span><br><span class="line">                           webXml.isMetadataComplete(), javaClassCache);</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line"></span><br><span class="line">           // Step 5. Process JARs for annotations and</span><br><span class="line">           // @HandlesTypes matches - only need to process those fragments we</span><br><span class="line">           // are going to use (remember orderedFragments includes any</span><br><span class="line">           // container fragments)</span><br><span class="line">           if (ok) &#123;</span><br><span class="line">               processAnnotations(</span><br><span class="line">                       orderedFragments, webXml.isMetadataComplete(), javaClassCache);</span><br><span class="line">           &#125;</span><br><span class="line"></span><br><span class="line">           // Cache, if used, is no longer required so clear it</span><br><span class="line">           javaClassCache.clear();</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       if (!webXml.isMetadataComplete()) &#123;</span><br><span class="line">           // Step 6. Merge web-fragment.xml files into the main web.xml</span><br><span class="line">           // file.</span><br><span class="line">           if (ok) &#123;</span><br><span class="line">               ok = webXml.merge(orderedFragments);</span><br><span class="line">           &#125;</span><br><span class="line"></span><br><span class="line">           // Step 7. Apply global defaults</span><br><span class="line">           // Have to merge defaults before JSP conversion since defaults</span><br><span class="line">           // provide JSP servlet definition.</span><br><span class="line">           webXml.merge(defaults);</span><br><span class="line"></span><br><span class="line">           // Step 8. Convert explicitly mentioned jsps to servlets</span><br><span class="line">           if (ok) &#123;</span><br><span class="line">               convertJsps(webXml);</span><br><span class="line">           &#125;</span><br><span class="line"></span><br><span class="line">           // Step 9. Apply merged web.xml to Context</span><br><span class="line">           if (ok) &#123;</span><br><span class="line">               configureContext(webXml);</span><br><span class="line">           &#125;</span><br><span class="line">       &#125; else &#123;</span><br><span class="line">           webXml.merge(defaults);</span><br><span class="line">           convertJsps(webXml);</span><br><span class="line">           configureContext(webXml);</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       if (context.getLogEffectiveWebXml()) &#123;</span><br><span class="line">           log.info(&quot;web.xml:\n&quot; + webXml.toXml());</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       // Always need to look for static resources</span><br><span class="line">       // Step 10. Look for static resources packaged in JARs</span><br><span class="line">       if (ok) &#123;</span><br><span class="line">           // Spec does not define an order.</span><br><span class="line">           // Use ordered JARs followed by remaining JARs</span><br><span class="line">           Set&lt;WebXml&gt; resourceJars = new LinkedHashSet&lt;&gt;();</span><br><span class="line">           for (WebXml fragment : orderedFragments) &#123;</span><br><span class="line">               resourceJars.add(fragment);</span><br><span class="line">           &#125;</span><br><span class="line">           for (WebXml fragment : fragments.values()) &#123;</span><br><span class="line">               if (!resourceJars.contains(fragment)) &#123;</span><br><span class="line">                   resourceJars.add(fragment);</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">           processResourceJARs(resourceJars);</span><br><span class="line">           // See also StandardContext.resourcesStart() for</span><br><span class="line">           // WEB-INF/classes/META-INF/resources configuration</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       // Step 11. Apply the ServletContainerInitializer config to the</span><br><span class="line">       // context</span><br><span class="line">       if (ok) &#123;</span><br><span class="line">           for (Map.Entry&lt;ServletContainerInitializer,</span><br><span class="line">                   Set&lt;Class&lt;?&gt;&gt;&gt; entry :</span><br><span class="line">                       initializerClassMap.entrySet()) &#123;</span><br><span class="line">               if (entry.getValue().isEmpty()) &#123;</span><br><span class="line">                   context.addServletContainerInitializer(</span><br><span class="line">                           entry.getKey(), null);</span><br><span class="line">               &#125; else &#123;</span><br><span class="line">                   context.addServletContainerInitializer(</span><br><span class="line">                           entry.getKey(), entry.getValue());</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure></p>
<p>（2）mergeParameters<br>步骤（1）中会将web.xml中的context-param元素设置到context的parameters里，此处则是把parameters设置到servletContext里。</p>
<p>（3）启动listener<br>步骤（1）中会将web.xml中的listener元素设置到context的applicationListeners里，<br>此处则取出listener类名，创建实例，并将listener分为两类<br>eventlistener：ServletRequestAttributeListener、ServletRequestListener、HttpSessionIdListener、HttpSessionAttributeListener<br>lifecyclelistener：ServletContextListener、HttpSessionListener<br>对于ServletContextListener，会调用listener.contextInitialized(event)</p>
<p>（4）启动filter<br>步骤（1）中会将web.xml中的filter元素设置到filter的filterdef里，此处则会实例化filter设置到filterConfigs里。</p>
<p>（5）启动servlet<br>步骤（1）中会将web.xml中的servlet元素封装成wrapper并调用addChild方法设置到Context里，<br>此处则会检查是否需要loadonstartup，如果需要则load。</p>
<p>web.xml被加载</p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/11/14/Spring-IOC/" rel="next" title="Spring IOC">
                <i class="fa fa-chevron-left"></i> Spring IOC
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/11/22/IDEA快捷键/" rel="prev" title="IDEA快捷键">
                IDEA快捷键 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">xiehuan</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">28</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                
                  <span class="site-state-item-count">7</span>
                  <span class="site-state-item-name">分类</span>
                
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                
                  <span class="site-state-item-count">27</span>
                  <span class="site-state-item-name">标签</span>
                
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#StandardContext类"><span class="nav-number">1.</span> <span class="nav-text">StandardContext类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ContextConfig类"><span class="nav-number">2.</span> <span class="nav-text">ContextConfig类</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">xiehuan</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        







       <p>Hosted by <a href="https://pages.coding.me" style="font-weight: bold">Coding Pages</a></p>
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
